//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/.
// 			VisualNovelToolkit		     /_/_/_/_/_/_/_/_/_/.
// Copyright ©2013 - Sol-tribe.	/_/_/_/_/_/_/_/_/_/.
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace ViNoToolkit{

	/// <summary>
	/// Scene creator.
	/// </summary>
	[ ExecuteInEditMode ]
	public class SceneCreator : MonoBehaviour {
		static private SceneCreator m_Instance;
		static public SceneCreator Instance{
			get{
				return m_Instance;
			}
		}
		
		public bool awakeAndDestroy;
		public float fadeoutAndDestroyWaitTime = 1f;

		static public bool _FADEIN_AT_CREATE = true;
		static private bool m_DestroyRequested;			// Destroy Calling Locker .

		static public SceneData.SceneNodeData CreateNodeData( Hashtable attrTable ){
			SceneData.SceneNodeData data = new SceneData.SceneNodeData();
			data.name = attrTable["name"] as string;
			data.parentname = attrTable["parentname"] as string;

			ParamUtil.SetFloatAttr( out data.posX , "posX" , attrTable , 0f );
			ParamUtil.SetFloatAttr( out data.posY , "posY" , attrTable , 0f );
			ParamUtil.SetFloatAttr( out data.posZ , "posZ" , attrTable , 0f );

			ParamUtil.SetFloatAttr( out data.rotX , "rotX" , attrTable , 0f );
			ParamUtil.SetFloatAttr( out data.rotY , "rotY" , attrTable , 0f );
			ParamUtil.SetFloatAttr( out data.rotZ , "rotZ" , attrTable , 0f );

			ParamUtil.SetFloatAttr( out data.sclX , "sclX" , attrTable , 1f );
			ParamUtil.SetFloatAttr( out data.sclY , "sclY" , attrTable , 1f );
			ParamUtil.SetFloatAttr( out data.sclZ , "sclZ" , attrTable , 1f );

			data.uiAtlasName = attrTable["uiAtlasName"] as string;
			data.texturePath = attrTable["texturePath"] as string;
			ParamUtil.SetFloatAttr( out data.alpha , "alpha" , attrTable , 1f );
			if( attrTable.ContainsKey( "show") ){
				data.show = ViNoStringExtensions.IsTrueOrYes( attrTable["show"] as string  );
			}
			if( attrTable.ContainsKey( "makePixelPerfect") ){
				data.makePixelPerfect = ViNoStringExtensions.IsTrueOrYes( attrTable["makePixelPerfect"] as string  );
			}	
			return data;	
		}

		static public void CreateScene( Scene sceneData , bool fadeInStart ){
			_FADEIN_AT_CREATE = fadeInStart;

			if( m_DestroyRequested ){
				Instance.StartCoroutine( "CreateSceneWhenDestroyed" , sceneData );
			}
			else{
				Create( sceneData );
			}
	//		}
		}

		static public GameObject Create( SceneData.SceneNodeData data ){
			ViNoSceneManager sm = GameObject.FindObjectOfType( typeof( ViNoSceneManager) ) as ViNoSceneManager;
			GameObject go =  sm.CreateSceneNode( ref data );
			return go;
		}

		static public void Create( Scene sceneData ){
			ViNoSceneManager sm = GameObject.FindObjectOfType( typeof( ViNoSceneManager) ) as ViNoSceneManager;
			for( int i=0;i<sceneData.sceneNodesData.Length;i++){
				sm.CreateSceneNode( ref sceneData.sceneNodesData[ i ] );
			}		
		}

		// root is not destroyed.
		static public void DestroyScene( GameObject advSceneRoot , bool immediate ){
			if( Application.isPlaying ){				
				if( immediate ){				
					DestroySceneImmediate( advSceneRoot );
				}
				else{
					if( m_DestroyRequested ){
	//					Debug.Log( "<color=cyan>Destroy Already Requested...</color>");
						return;
					}
					if( advSceneRoot.transform.GetChildCount() > 0 ){
						VM vm = VM.Instance;
						if( vm != null && Application.isPlaying ){
							vm.EnableUpdate( false );
						}
	//					Debug.Log( "<color=cyan>Start Destroying...</color>");
						Instance.StartCoroutine( "FadeoutAndDestroy" , advSceneRoot );
					}
					else{
						m_DestroyRequested = false;
					}
				}
			}
			else{
				DestroySceneImmediate( advSceneRoot );
			}
		}

		static public void DestroySceneImmediate( GameObject advSceneRoot ){
			// Destroy Created Materials to avoid Leaking .
	//		Debug.Log( "Destroy Root:" + advSceneRoot.name );

			ViNoSceneManager sm = GameObject.FindObjectOfType( typeof(ViNoSceneManager) ) as ViNoSceneManager;
			sm.OnFadeoutAndDestroy( advSceneRoot );

			// Destroy Under ME.
			ViNoGOExtensions.DestroyImmediateChildren( advSceneRoot.name );	
		}

		IEnumerator CreateSceneWhenDestroyed( Scene sceneData ){
	//		VM vm = VM.Instance;
	//		if( vm != null && Application.isPlaying ){
	//			vm.EnableUpdate( false );
			if( Application.isPlaying ){
				ViNoAPI.EnableUpdateADV( false );
			}

			while( m_DestroyRequested ){
				Debug.Log( "waiting for Cleaning Up the scene...");
				yield return new WaitForSeconds( 0.01f );
			}
	//		Debug.Log( "CreateScene CreateSceneWhenDestroyed");
	//		Debug.Log( "_FADEIN_AT_CREATE:" + _FADEIN_AT_CREATE.ToString() );
			Create( sceneData );
	//		if( vm != null && Application.isPlaying ){
	//			vm.EnableUpdate( true );
			
			if( Application.isPlaying ){
				ViNoAPI.EnableUpdateADV( true );
			}
		}

			/// <summary>
			/// Fadeouts the and destroy.
			/// </summary>
			/// <returns>The and destroy.</returns>
			/// <param name="destroyRoot">Destroy root.</param>
		IEnumerator FadeoutAndDestroy( GameObject destroyRoot ){
			m_DestroyRequested = true;
			VM vm = VM.Instance;

			ViNoSceneManager sm = ViNoSceneManager.Instance;
			sm.PreFadeoutAndDestroy( destroyRoot );

			yield return new WaitForSeconds( fadeoutAndDestroyWaitTime );

			sm.OnFadeoutAndDestroy( destroyRoot );

			// Destroy Under ME.
			ViNoGOExtensions.DestroyChildren( destroyRoot );

			if( vm != null && Application.isPlaying ){
				vm.EnableUpdate( true );
			}

			m_DestroyRequested = false;
		}

		void Awake(){
			m_Instance = this;
			if( Application.isPlaying ){
				if( awakeAndDestroy ){
		//			Debug.Log( "Awake and Destroy ADV SCENE...");
					DestroySceneImmediate( this.gameObject );
				}
			}
		}

	}
}
